package curd

import (
	"reflect"

	"gorm.io/gorm"
	"gorm.io/gorm/clause"
	"gorm.io/gorm/schema"
)

var (
	_ gorm.Plugin = &CURD{}
)

type CURD struct {
}

func New() *CURD {
	return &CURD{}
}

func (s *CURD) Name() string {
	return "gorm:curd"
}

func (s *CURD) Initialize(db *gorm.DB) (err error) {
	_ = db.Callback().Create().Before("gorm:create").Register("operator_before_create", s.BeforeCreate())
	return
}

func (s *CURD) BeforeCreate() func(db *gorm.DB) {
	return func(db *gorm.DB) {
		if db.Statement.Schema != nil && len(db.Statement.Selects) == 0 {
			selectColumns := getNonDefaultFields(db.Statement.Schema, db.Statement.ReflectValue)
			if len(selectColumns) > 0 {
				db.Statement.Selects = selectColumns
			}
		}
	}
}

func (s *CURD) AfterCallback() func(db *gorm.DB) {
	return func(db *gorm.DB) {
	}
}

func getNonDefaultFields(schema *schema.Schema, value reflect.Value) []string {
	var fields []string

	// 处理切片中的每个元素
	if value.Kind() == reflect.Slice {
		for i := 0; i < value.Len(); i++ {
			elem := value.Index(i)
			if elem.Kind() == reflect.Ptr {
				elem = elem.Elem()
			}
			if elem.Kind() == reflect.Struct {
				fields = append(fields, getNonDefaultFieldsFromStruct(schema, elem)...)
			}
		}
	} else if value.Kind() == reflect.Ptr {
		value = value.Elem()
		if value.Kind() == reflect.Struct {
			fields = append(fields, getNonDefaultFieldsFromStruct(schema, value)...)
		}
	}

	return fields
}

func getNonDefaultFieldsFromStruct(schema *schema.Schema, value reflect.Value) []string {
	var fields []string

	for _, field := range schema.Fields {
		fieldValue := value.FieldByName(field.Name)
		if fieldValue.IsValid() && !reflect.DeepEqual(fieldValue.Interface(), reflect.Zero(fieldValue.Type()).Interface()) {
			fields = append(fields, clause.Column{Name: field.DBName}.Name)
		}
	}

	return fields
}
